# Calibre-Web Automated – fork of Calibre-Web
# Copyright (C) 2018-2025 Calibre-Web contributors
# Copyright (C) 2024-2025 Calibre-Web Automated contributors
# SPDX-License-Identifier: GPL-3.0-or-later
# See CONTRIBUTORS for full list of authors.

# This file is is mostly taken from audio.py from Ozzieisaacs at calibre-web

import base64
import os
from collections import namedtuple

import mutagen

try:
    from wand.image import Image

    use_IM = True
except (ImportError, RuntimeError) as e:
    use_IM = False

BookMeta = namedtuple(
    "BookMeta",
    "file_path, extension, title, author, cover, description, tags, series, "
    "series_id, languages, publisher, pubdate, identifiers",
)

NO_JPEG_EXTENSIONS = [".png", ".webp", ".bmp"]
COVER_EXTENSIONS = [".png", ".webp", ".bmp", ".jpg", ".jpeg"]


def cover_processing(tmp_file_path, img, extension):
    # tmp_cover_name = os.path.join(os.path.dirname(tmp_file_name), 'cover.jpg')
    tmp_cover_name = tmp_file_path + ".jpg"
    if extension in NO_JPEG_EXTENSIONS:
        if use_IM:
            with Image(blob=img) as imgc:
                imgc.format = "jpeg"
                imgc.transform_colorspace("srgb")
                imgc.save(filename=tmp_cover_name)
                return tmp_cover_name
        else:
            return None
    if img:
        with open(tmp_cover_name, "wb") as f:
            f.write(img)
        return tmp_cover_name
    else:
        return None


def get_audio_file_info(
    tmp_file_path, original_file_extension, original_file_name, no_cover_processing
):
    tmp_cover_name = None
    audio_file = mutagen.File(tmp_file_path)
    comments = None
    if original_file_extension in [".mp3", ".wav", ".aiff"]:
        cover_data = list()
        for key, val in audio_file.tags.items():
            if key.startswith("APIC:"):
                cover_data.append(val)
            if key.startswith("COMM:"):
                comments = val.text[0]
        title = (
            audio_file.tags.get("TIT2").text[0] if "TIT2" in audio_file.tags else None
        )
        author = (
            audio_file.tags.get("TPE1").text[0] if "TPE1" in audio_file.tags else None
        )
        if author is None:
            author = (
                audio_file.tags.get("TPE2").text[0]
                if "TPE2" in audio_file.tags
                else None
            )
        tags = (
            audio_file.tags.get("TCON").text[0] if "TCON" in audio_file.tags else None
        )  # Genre
        series = (
            audio_file.tags.get("TALB").text[0] if "TALB" in audio_file.tags else None
        )  # Album
        series_id = (
            audio_file.tags.get("TRCK").text[0] if "TRCK" in audio_file.tags else None
        )  # track no.
        publisher = (
            audio_file.tags.get("TPUB").text[0] if "TPUB" in audio_file.tags else None
        )
        pubdate = (
            str(audio_file.tags.get("TDRL").text[0])
            if "TDRL" in audio_file.tags
            else None
        )
        if not pubdate:
            pubdate = (
                str(audio_file.tags.get("TDRC").text[0])
                if "TDRC" in audio_file.tags
                else None
            )
            if not pubdate:
                pubdate = (
                    str(audio_file.tags.get("TDOR").text[0])
                    if "TDOR" in audio_file.tags
                    else None
                )
        if cover_data and not no_cover_processing:
            cover_info = cover_data[0]
            for dat in cover_data:
                if dat.type == mutagen.id3.PictureType.COVER_FRONT:
                    cover_info = dat
                    break
            tmp_cover_name = cover_processing(
                tmp_file_path, cover_info.data, "." + cover_info.mime[-3:]
            )
    elif original_file_extension in [".ogg", ".flac", ".opus", ".ogv"]:
        title = audio_file.tags.get("TITLE")[0] if "TITLE" in audio_file else None
        author = audio_file.tags.get("ARTIST")[0] if "ARTIST" in audio_file else None
        comments = (
            audio_file.tags.get("COMMENTS")[0] if "COMMENTS" in audio_file else None
        )
        tags = (
            audio_file.tags.get("GENRE")[0] if "GENRE" in audio_file else None
        )  # Genre
        series = audio_file.tags.get("ALBUM")[0] if "ALBUM" in audio_file else None
        series_id = (
            audio_file.tags.get("TRACKNUMBER")[0]
            if "TRACKNUMBER" in audio_file
            else None
        )
        publisher = audio_file.tags.get("LABEL")[0] if "LABEL" in audio_file else None
        pubdate = audio_file.tags.get("DATE")[0] if "DATE" in audio_file else None
        cover_data = audio_file.tags.get("METADATA_BLOCK_PICTURE")
        if not no_cover_processing:
            if cover_data:
                cover_info = mutagen.flac.Picture(base64.b64decode(cover_data[0]))
                tmp_cover_name = cover_processing(
                    tmp_file_path, cover_info.data, "." + cover_info.mime[-3:]
                )
            if hasattr(audio_file, "pictures"):
                cover_info = audio_file.pictures[0]
                for dat in audio_file.pictures:
                    if dat.type == mutagen.id3.PictureType.COVER_FRONT:
                        cover_info = dat
                        break
                tmp_cover_name = cover_processing(
                    tmp_file_path, cover_info.data, "." + cover_info.mime[-3:]
                )
    elif original_file_extension in [".aac"]:
        title = audio_file.tags.get("Title").value if "Title" in audio_file else None
        author = audio_file.tags.get("Artist").value if "Artist" in audio_file else None
        comments = (
            audio_file.tags.get("Comment").value if "Comment" in audio_file else None
        )
        tags = audio_file.tags.get("Genre").value if "Genre" in audio_file else None
        series = audio_file.tags.get("Album").value if "Album" in audio_file else None
        series_id = (
            audio_file.tags.get("Track").value if "Track" in audio_file else None
        )
        publisher = (
            audio_file.tags.get("Label").value if "Label" in audio_file else None
        )
        pubdate = audio_file.tags.get("Year").value if "Year" in audio_file else None
        cover_data = audio_file.tags["Cover Art (Front)"]
        if cover_data and not no_cover_processing:
            tmp_cover_name = tmp_file_path + ".jpg"
            with open(tmp_cover_name, "wb") as cover_file:
                cover_file.write(cover_data.value.split(b"\x00", 1)[1])
    elif original_file_extension in [".asf"]:
        title = audio_file.tags.get("Title")[0].value if "Title" in audio_file else None
        author = (
            audio_file.tags.get("Artist")[0].value if "Artist" in audio_file else None
        )
        comments = (
            audio_file.tags.get("Comments")[0].value
            if "Comments" in audio_file
            else None
        )
        tags = audio_file.tags.get("Genre")[0].value if "Genre" in audio_file else None
        series = (
            audio_file.tags.get("Album")[0].value if "Album" in audio_file else None
        )
        series_id = (
            audio_file.tags.get("Track")[0].value if "Track" in audio_file else None
        )
        publisher = (
            audio_file.tags.get("Label")[0].value if "Label" in audio_file else None
        )
        pubdate = audio_file.tags.get("Year")[0].value if "Year" in audio_file else None
        cover_data = audio_file.tags.get("WM/Picture", None)
        if cover_data and not no_cover_processing:
            tmp_cover_name = tmp_file_path + ".jpg"
            with open(tmp_cover_name, "wb") as cover_file:
                cover_file.write(cover_data[0].value)
    elif original_file_extension in [".mp4", ".m4a", ".m4b"]:
        title = audio_file.tags.get("©nam")[0] if "©nam" in audio_file.tags else None
        author = audio_file.tags.get("©ART")[0] if "©ART" in audio_file.tags else None
        comments = audio_file.tags.get("©cmt")[0] if "©cmt" in audio_file.tags else None
        tags = audio_file.tags.get("©gen")[0] if "©gen" in audio_file.tags else None
        series = audio_file.tags.get("©alb")[0] if "©alb" in audio_file.tags else None
        series_id = (
            str(audio_file.tags.get("trkn")[0][0])
            if "trkn" in audio_file.tags
            else None
        )
        publisher = ""
        pubdate = audio_file.tags.get("©day")[0] if "©day" in audio_file.tags else None
        cover_data = audio_file.tags.get("covr", None)
        if cover_data and not no_cover_processing:
            cover_type = None
            for c in cover_data:
                if c.imageformat == mutagen.mp4.AtomDataType.JPEG:
                    cover_type = ".jpg"
                    cover_bin = c
                    break
                elif c.imageformat == mutagen.mp4.AtomDataType.PNG:
                    cover_type = ".png"
                    cover_bin = c
                    break
            if cover_type:
                tmp_cover_name = cover_processing(tmp_file_path, cover_bin, cover_type)
            # else:
            # logger.error("Unknown covertype in file {} ".format(original_file_name))

    return BookMeta(
        file_path=tmp_file_path,
        extension=original_file_extension,
        title=title or original_file_name,
        author="Unknown" if author is None else author,
        cover=tmp_cover_name,
        description="" if comments is None else comments,
        tags="" if tags is None else tags,
        series="" if series is None else series,
        series_id="1" if series_id is None else series_id.split("/")[0],
        languages="",
        publisher="" if publisher is None else publisher,
        pubdate="" if pubdate is None else pubdate,
        identifiers=[],
    )
